﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using SCEM;
using System.IO;
using System.Reflection;
using System.Data;
using System.Data.SqlServerCe;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace SCEMTest.Util
{
    /// <summary>
    /// Classe contendo métodos auxiliares para testes.
    /// </summary>
    public class TestHelper
    {
        /// <summary>
        /// Realiza asserts para garantir que um conjunto de propriedades é igual em dois objetos distintos.
        /// </summary>
        /// <typeparam name="T">Tipo do objeto.</typeparam>
        /// <param name="expected">Objeto cujas propriedades devem ser tomadas como referência para o assert.</param>
        /// <param name="actual">O outro objeto.</param>
        /// <param name="propertiesToCheck">Uma coleção com os nomes das propriedades a serem comparadas.</param>
        public static void AssertPropertiesAreEqual<T>(T expected, T actual, ISet<string> propertiesToCheck) where T : class
        {
            if (expected == null)
                throw new ArgumentNullException("expected");
            if (actual == null)
                throw new ArgumentNullException("actual");
            if (propertiesToCheck == null)
                throw new ArgumentNullException("propertiesToCheck");

            IEnumerable<PropertyInfo> properties = typeof(T).GetProperties();
            foreach (PropertyInfo property in properties)
            {
                if (propertiesToCheck.Contains(property.Name))
                {
                    // A propriedade atual deve ser verificada
                    if (!property.CanRead)
                        throw new ArgumentException("Erro ao ler a propriedade: " + property.Name);

                    Object expectedValue = typeof(T).GetProperty(property.Name).GetValue(expected, null);
                    Object actualValue = typeof(T).GetProperty(property.Name).GetValue(actual, null);
                    Assert.AreEqual(expectedValue, actualValue);

                    // Remover a propriedade da lista de propriedades a serem verificadas
                    propertiesToCheck.Remove(property.Name);
                }
            }

            // Verificar se realmente todas as propriedades indicadas pelo usuário foram verificadas
            if (propertiesToCheck.Count() > 0)
                throw new ArgumentException("Uma ou mais propriedades não foram localizadas no tipo fornecido");
        }

        /// <summary>
        /// Reinicializa completamente o banco de dados de testes, tomando o cuidado de popular o banco com as entidades iniciais.
        /// </summary>
        public static void ReinitializeTestDatabase()
        {
            string connectionString = ConfigurationManager.ConnectionStrings["SCEMContainerTest"].ConnectionString;
            string directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
          
            string file1 = File.OpenText(directory + "\\SCEM.edmx.sqlce").ReadToEnd();
            file1 = file1.Replace("GO", "");
            string file2 = File.OpenText(directory + "\\SCEM.PopulateDB.sqlce").ReadToEnd();
            file2 = file2.Replace("GO", "");

            using (SqlCeConnection sqlConnection = new SqlCeConnection(connectionString))
            {
                sqlConnection.Open();

                IEnumerable<string> commands = file1.Split(new char[] { ';' });
                commands = commands.Concat(file2.Split(new char[] { ';' }));

                foreach (string command in commands)
                {
                    using (SqlCeCommand sqlCommand = new SqlCeCommand(command, sqlConnection))
                    {
                        try { sqlCommand.ExecuteNonQuery(); }
                        catch (Exception) { } // Um dos "comandos" de cada arquivo vai ser composto apenas de comentários e vai invariavelmente falhar
                    }
                }
            }
        }

    }
}
